package com.aqielife.demo.example.lambda;

import java.util.ArrayList;
import java.util.List;
import java.util.function.*;

class Dog {
    private String name = "哮天犬";

    /**
     * 默认10斤狗粮
     */
    private int food = 10;

    public Dog() {

    }

    /**
     * 带参数的构造函数
     *
     * @param name
     */
    public Dog(String name) {
        this.name = name;
    }

    /**
     * 狗叫，静态方法 没有可以访问对象实例的 this指针
     *
     * @param dog
     */
    public static void bark(Dog dog) {
        System.out.println(dog + "叫了");
    }

    /**
     * 吃狗粮 JDK
     *
     * 默认会把当前实例传入到非静态方法，参数名为this，位置是第一个；
     *
     * @param num
     * @return 还剩下多少斤
     */
    public int eat(Dog this,int num) {
        System.out.println("吃了" + num + "斤狗粮");
        this.food -= num;
        return this.food;
    }

    @Override
    public String toString() {
        return this.name;
    }
}

public class MethodReferenceDemo {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat(3);

        // 方法引用
        Consumer<String> consumer = System.out::println;
        consumer.accept("接受的数据");

        // 静态方法的方法引用【类::方法名】 (输入 dog实例， 输出null 是一个消费者)
        Consumer<Dog> consumer2 = Dog::bark;    // dog1 -> Dog.bark(dog1);
        consumer2.accept(dog);

        // 非静态方法，【实例::方法名】
        // Function<Integer, Integer> function = dog::eat;
        // 输入输出均是Integer 可以转换
        // UnaryOperator<Integer> function = dog::eat;
        IntUnaryOperator function = dog::eat;
        // dog = null;  // 实例置空引用不受影响
        System.out.println("还剩下 " + function.applyAsInt(2) + "斤");

        // 非静态方法 【类名::方法名】 有第一个参数this
        BiFunction<Dog,Integer,Integer> function1 = Dog::eat;
        System.out.println("还剩下 " + function1.apply(dog,2) + "斤");

        // (无参)构造函数的方法引用， 方法名写死new
        Supplier<Dog> supplier = Dog::new;       // 输入是空，构造函数会返回实例，是个提供者
        System.out.println("创建了新对象" + supplier.get());

        // 有参数构造方法
        Function<String, Dog> function2 = Dog::new;
        System.out.println("创建了新对象" + function2.apply("旺财"));

        // java 传值引用
        List<String> list = new ArrayList<>();
        test(list);
        System.out.println(list); // [] 非 null
    }

    // java 传递的是值不是引用
    private static void test(List<String> list){
        list = null;
    }
}
